home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / byacc 1.8.2 / reader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-04  |  36.0 KB  |  2,065 lines  |  [TEXT/R*ch]

  1. #include "defs.h"
  2.  
  3. /*  The line size must be a positive integer.  One hundred was chosen    */
  4. /*  because few lines in Yacc input grammars exceed 100 characters.    */
  5. /*  Note that if a line exceeds LINESIZE characters, the line buffer    */
  6. /*  will be expanded to accomodate it.                    */
  7.  
  8. #define LINESIZE 100
  9.  
  10. char *cache;
  11. int cinc, cache_size;
  12.  
  13. int ntags, tagmax;
  14. char **tag_table;
  15.  
  16. char saw_eof, unionized;
  17. char *cptr, *line;
  18. int linesize;
  19.  
  20. bucket *goal;
  21. int prec;
  22. int gensym;
  23. char last_was_action;
  24.  
  25. int maxitems;
  26. bucket **pitem;
  27.  
  28. int maxrules;
  29. bucket **plhs;
  30.  
  31. int name_pool_size;
  32. char *name_pool;
  33.  
  34. char line_format[] = "#line %d \"%s\"\n";
  35.  
  36. /* dollar sign is allowed in identifiers */
  37. #define dollar_ok()    (language==C)
  38.  
  39.  
  40. static void cachec _P_((int c));
  41. static void get_line _P_((void));
  42. static char *dup_line _P_((void));
  43. static void skip_comment _P_((void));
  44. static int nextc _P_((void));
  45. static int keyword _P_((void));
  46. static void copy_ident _P_((void));
  47. static void copy_text _P_((void));
  48. static void perl_comment _P_((FILE *text_file, FILE *other_file));
  49. static void copy_union _P_((void));
  50. static int hexval _P_((int c));
  51. static bucket *get_literal _P_((void));
  52. static int is_reserved _P_((char *name));
  53. static bucket *get_name _P_((void));
  54. static int get_number _P_((void));
  55. static char *get_tag _P_((void));
  56. static void declare_tokens _P_((int assoc));
  57. static void declare_types _P_((void));
  58. static void declare_start _P_((void));
  59. static void read_declarations _P_((void));
  60. static void initialize_grammar _P_((void));
  61. static void expand_items _P_((void));
  62. static void expand_rules _P_((void));
  63. static void advance_to_start _P_((void));
  64. static void start_rule _P_((register bucket *bp, int s_lineno));
  65. static void end_rule _P_((void));
  66. static void insert_empty_rule _P_((void));
  67. static void add_symbol _P_((void));
  68. static void copy_action _P_((void));
  69. static int mark_symbol _P_((void));
  70. static void read_grammar _P_((void));
  71. static void free_tags _P_((void));
  72. static void pack_names _P_((void));
  73. static void check_symbols _P_((void));
  74. static void pack_symbols _P_((void));
  75. static void pack_grammar _P_((void));
  76. static void print_grammar _P_((void));
  77.  
  78.  
  79. #if __STDC__
  80. static void cachec(int c)
  81. #else
  82. static void cachec(c)
  83. int c;
  84. #endif
  85. {
  86.     assert(cinc >= 0);
  87.     if (cinc >= cache_size)
  88.     {
  89.     cache_size += 256;
  90.     cache = REALLOC(cache, cache_size);
  91.     }
  92.     cache[cinc] = c;
  93.     ++cinc;
  94. }
  95.  
  96.  
  97. #if __STDC__
  98. static void get_line(void)
  99. #else
  100. static void get_line()
  101. #endif
  102. {
  103.     register FILE *f = input_file;
  104.     register int c;
  105.     register int i;
  106.  
  107.     if (saw_eof || (c = getc(f)) == EOF)
  108.     {
  109.     if (line) { FREE(line); line = 0; }
  110.     cptr = 0;
  111.     saw_eof = 1;
  112.     return;
  113.     }
  114.  
  115.     if (line == 0 || linesize != (LINESIZE + 1))
  116.     {
  117.     if (line) FREE(line);
  118.     linesize = LINESIZE + 1;
  119.     line = MALLOC(linesize);
  120.     }
  121.  
  122.     i = 0;
  123.     ++lineno;
  124.     for (;;)
  125.     {
  126.     line[i]     =  c;
  127.     if (c == '\n') { cptr = line; return; }
  128.     if (++i >= linesize)
  129.     {
  130.         linesize += LINESIZE;
  131.         line = REALLOC(line, linesize);
  132.     }
  133.     c = getc(f);
  134.     if (c ==  EOF)
  135.     {
  136.         line[i] = '\n';
  137.         saw_eof = 1;
  138.         cptr = line;
  139.         return;
  140.     }
  141.     }
  142. }
  143.  
  144.  
  145. #if __STDC__
  146. static char *dup_line(void)
  147. #else
  148. static char *dup_line()
  149. #endif
  150. {
  151.     register char *p, *s, *t;
  152.  
  153.     if (line == 0) return (0);
  154.     s = line;
  155.     while (*s != '\n') ++s;
  156.     p = MALLOC(s - line + 1);
  157.  
  158.     s = line;
  159.     t = p;
  160.     while ((*t++ = *s++) != '\n') continue;
  161.     return (p);
  162. }
  163.  
  164.  
  165. #if __STDC__
  166. static void skip_comment(void)
  167. #else
  168. static void skip_comment()
  169. #endif
  170. {
  171.     register char *s;
  172.  
  173.     int st_lineno = lineno;
  174.     char *st_line = dup_line();
  175.     char *st_cptr = st_line + (cptr - line);
  176.  
  177.     s = cptr + 2;
  178.     for (;;)
  179.     {
  180.     if (*s == '*' && s[1] == '/')
  181.     {
  182.         cptr = s + 2;
  183.         FREE(st_line);
  184.         return;
  185.     }
  186.     if (*s == '\n')
  187.     {
  188.         get_line();
  189.         if (line == 0)
  190.         unterminated_comment(st_lineno, st_line, st_cptr);
  191.         s = cptr;
  192.     }
  193.     else
  194.         ++s;
  195.     }
  196. }
  197.  
  198.  
  199. #if __STDC__
  200. static int nextc(void)
  201. #else
  202. static int nextc()
  203. #endif
  204. {
  205.     register char *s;
  206.  
  207.     if (line == 0)
  208.     {
  209.     get_line();
  210.     if (line == 0)
  211.         return (EOF);
  212.     }
  213.  
  214.     s = cptr;
  215.     for (;;)
  216.     {
  217.     switch (*s)
  218.     {
  219.     case '\n':
  220.         get_line();
  221.         if (line == 0) return (EOF);
  222.         s = cptr;
  223.         break;
  224.  
  225.     case ' ':
  226.     case '\t':
  227.     case '\f':
  228.     case '\r':
  229.     case '\v':
  230.     case ',':
  231.     case ';':
  232.         ++s;
  233.         break;
  234.  
  235.     case '\\':
  236.         cptr = s;
  237.         return ('%');
  238.  
  239.     case '#':
  240.         if (language == PERL) {
  241.         get_line();
  242.         if (line == 0) return (EOF);
  243.         s = cptr;
  244.         break;
  245.         }
  246.         cptr = s;
  247.         return (*s);
  248.  
  249.     case '/':
  250.         if (s[1] == '*')
  251.         {
  252.         cptr = s;
  253.         skip_comment();
  254.         s = cptr;
  255.         break;
  256.         }
  257.         else if (s[1] == '/')
  258.         {
  259.         get_line();
  260.         if (line == 0) return (EOF);
  261.         s = cptr;
  262.         break;
  263.         }
  264.         cptr = s;
  265.         return (*s);
  266.  
  267.     default:
  268.         cptr = s;
  269.         return (*s);
  270.     }
  271.     }
  272. }
  273.  
  274.  
  275. #if __STDC__
  276. static int keyword(void)
  277. #else
  278. static int keyword()
  279. #endif
  280. {
  281.     register int c;
  282.     char *t_cptr = cptr;
  283.  
  284.     c = *++cptr;
  285.     if (isalpha(c))
  286.     {
  287.     cinc = 0;
  288.     for (;;)
  289.     {
  290.         if (isalpha(c))
  291.         {
  292.         if (isupper(c)) c = tolower(c);
  293.         cachec(c);
  294.         }
  295.         else if (isdigit(c) || c == '_' || c == '.' || (dollar_ok() && c == '$'))
  296.         cachec(c);
  297.         else
  298.         break;
  299.         c = *++cptr;
  300.     }
  301.     cachec(NUL);
  302.  
  303.     if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
  304.         return (TOKEN);
  305.     if (strcmp(cache, "type") == 0)
  306.         return (TYPE);
  307.     if (strcmp(cache, "left") == 0)
  308.         return (LEFT);
  309.     if (strcmp(cache, "right") == 0)
  310.         return (RIGHT);
  311.     if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
  312.         return (NONASSOC);
  313.     if (strcmp(cache, "start") == 0)
  314.         return (START);
  315.     if (strcmp(cache, "union") == 0)
  316.         return (UNION);
  317.     if (strcmp(cache, "ident") == 0)
  318.         return (IDENT);
  319.     }
  320.     else
  321.     {
  322.     ++cptr;
  323.     if (c == '{')
  324.         return (TEXT);
  325.     if (c == '%' || c == '\\')
  326.         return (MARK);
  327.     if (c == '<')
  328.         return (LEFT);
  329.     if (c == '>')
  330.         return (RIGHT);
  331.     if (c == '0')
  332.         return (TOKEN);
  333.     if (c == '2')
  334.         return (NONASSOC);
  335.     }
  336.     syntax_error(lineno, line, t_cptr);
  337.     /*NOTREACHED*/
  338. }
  339.  
  340.  
  341. #if __STDC__
  342. static void copy_ident(void)
  343. #else
  344. static void copy_ident()
  345. #endif
  346. {
  347.     register int c;
  348.     register FILE *f = output_file;
  349.  
  350.     c = nextc();
  351.     if (c == EOF) unexpected_EOF();
  352.     if (c != '"') syntax_error(lineno, line, cptr);
  353.     ++outline;
  354.     fprintf(f, "#ident \"");
  355.     for (;;)
  356.     {
  357.     c = *++cptr;
  358.     if (c == '\n')
  359.     {
  360.         fprintf(f, "\"\n");
  361.         return;
  362.     }
  363.     putc(c, f);
  364.     if (c == '"')
  365.     {
  366.         putc('\n', f);
  367.         ++cptr;
  368.         return;
  369.     }
  370.     }
  371. }
  372.  
  373.  
  374. #if __STDC__
  375. static void copy_text(void)
  376. #else
  377. static void copy_text()
  378. #endif
  379. {
  380.     register int c;
  381.     int quote;
  382.     register FILE *f = text_file;
  383.     int need_newline = 0;
  384.     int t_lineno = lineno;
  385.     char *t_line = dup_line();
  386.     char *t_cptr = t_line + (cptr - line - 2);
  387.  
  388.     if (*cptr == '\n')
  389.     {
  390.     get_line();
  391.     if (line == 0)
  392.         unterminated_text(t_lineno, t_line, t_cptr);
  393.     }
  394.     if (!lflag) fprintf(f, line_format, lineno, input_file_name);
  395.  
  396. loop:
  397.     c = *cptr++;
  398.     switch (c)
  399.     {
  400.     case '\n':
  401.     next_line:
  402.     putc('\n', f);
  403.     need_newline = 0;
  404.     get_line();
  405.     if (line) goto loop;
  406.     unterminated_text(t_lineno, t_line, t_cptr);
  407.  
  408.     case '\'':
  409.     case '"':
  410.     {
  411.         int s_lineno = lineno;
  412.         char *s_line = dup_line();
  413.         char *s_cptr = s_line + (cptr - line - 1);
  414.  
  415.         quote = c;
  416.         putc(c, f);
  417.         for (;;)
  418.         {
  419.         c = *cptr++;
  420.         putc(c, f);
  421.         if (c == quote)
  422.         {
  423.             need_newline = 1;
  424.             FREE(s_line);
  425.             goto loop;
  426.         }
  427.         if (c == '\n')
  428.             unterminated_string(s_lineno, s_line, s_cptr);
  429.         if (c == '\\')
  430.         {
  431.             c = *cptr++;
  432.             putc(c, f);
  433.             if (c == '\n')
  434.             {
  435.             get_line();
  436.             if (line == 0)
  437.                 unterminated_string(s_lineno, s_line, s_cptr);
  438.             }
  439.         }
  440.         }
  441.     }
  442.  
  443.     case '/':
  444.     need_newline = 1;
  445.     c = *cptr;
  446.     if (c == '/')
  447.     {
  448.         if (language == PERL)
  449.         fprintf(f, (cptr == line + 1) ? ";#" : "#");
  450.         else
  451.         fprintf(f, "/*");
  452.         while ((c = *++cptr) != '\n')
  453.         {
  454.         if (c == '*' && cptr[1] == '/')
  455.             fprintf(f, "* ");
  456.         else
  457.             putc(c, f);
  458.         }
  459.         if (language == C)
  460.         fprintf(f, "*/");
  461.         goto next_line;
  462.     }
  463.     else if (c == '*')
  464.     {
  465.         int c_lineno = lineno;
  466.         char *c_line = dup_line();
  467.         char *c_cptr = c_line + (cptr - line - 1);
  468.  
  469.         if (language == PERL)
  470.         fprintf(f, (cptr == line + 1) ? ";#" : "#");
  471.         else
  472.         fprintf(f, "/*");
  473.         ++cptr;
  474.         for (;;)
  475.         {
  476.         c = *cptr++;
  477.         putc(c, f);
  478.         if (c == '*' && *cptr == '/')
  479.         {
  480.             if (language == C)
  481.             putc('/', f);
  482.             ++cptr;
  483.             FREE(c_line);
  484.             goto loop;
  485.         }
  486.         if (c == '\n')
  487.         {
  488.             get_line();
  489.             if (line == 0)
  490.             unterminated_comment(c_lineno, c_line, c_cptr);
  491.         }
  492.         }
  493.     }
  494.     else
  495.         putc('/', f);
  496.     goto loop;
  497.  
  498.     case '%':
  499.     case '\\':
  500.     if (*cptr == '}')
  501.     {
  502.         if (need_newline) putc('\n', f);
  503.         ++cptr;
  504.         FREE(t_line);
  505.         return;
  506.     }
  507.     putc(c, f);
  508.     need_newline = 1;
  509.     goto loop;
  510.  
  511.     case '#':
  512.     if (language == PERL) {
  513.         fprintf(f, (cptr == line + 1) ? ";#" : "#");
  514.         need_newline = 1;
  515.         while ((c = *cptr++) != '\n')
  516.         putc(c, f);
  517.         goto next_line;
  518.     }
  519.     putc(c, f);
  520.     need_newline = 1;
  521.     goto loop;
  522.     
  523.     default:
  524.     putc(c, f);
  525.     need_newline = 1;
  526.     goto loop;
  527.     }
  528. }
  529.  
  530. #if __STDC__
  531. static void perl_comment(FILE *text_file, FILE *other_file)
  532. #else
  533. static void perl_comment(text_file, other_file)
  534. FILE *text_file;
  535. FILE *other_file;
  536. #endif
  537. {
  538.     if (language == PERL)
  539.     {
  540.     fprintf(text_file, (cptr == line + 1) ? ";#" : "#");
  541.     if (dflag)
  542.         fprintf(other_file, (cptr == line + 1) ? ";#" : "#");
  543.     }
  544. }
  545.   
  546. #if __STDC__
  547. static void copy_union(void)
  548. #else
  549. static void copy_union()
  550. #endif
  551. {
  552.     register int c;
  553.     int quote;
  554.     int depth;
  555.     int u_lineno = lineno;
  556.     char *u_line = dup_line();
  557.     char *u_cptr = u_line + (cptr - line - 6);
  558.  
  559.     if (unionized) over_unionized(cptr - 6);
  560.     unionized = 1;
  561.  
  562.     if (!lflag)
  563.     fprintf(text_file, line_format, lineno, input_file_name);
  564.  
  565.     perl_comment(text_file, union_file);
  566.     fprintf(text_file, "typedef union");
  567.     if (dflag) fprintf(union_file, "typedef union");
  568.  
  569.     depth = 0;
  570. loop:
  571.     c = *cptr++;
  572.     putc(c, text_file);
  573.     if (dflag) putc(c, union_file);
  574.     switch (c)
  575.     {
  576.     case '\n':
  577.     next_line:
  578.     get_line();
  579.     if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
  580.     perl_comment(text_file, union_file);
  581.     goto loop;
  582.  
  583.     case '{':
  584.     ++depth;
  585.     goto loop;
  586.  
  587.     case '}':
  588.     if (--depth == 0)
  589.     {
  590.         fprintf(text_file, " %sSTYPE;\n", define_prefix);
  591.         FREE(u_line);
  592.         return;
  593.     }
  594.     goto loop;
  595.  
  596.     case '\'':
  597.     case '"':
  598.     {
  599.         int s_lineno = lineno;
  600.         char *s_line = dup_line();
  601.         char *s_cptr = s_line + (cptr - line - 1);
  602.  
  603.         quote = c;
  604.         for (;;)
  605.         {
  606.         c = *cptr++;
  607.         putc(c, text_file);
  608.         if (dflag) putc(c, union_file);
  609.         if (c == quote)
  610.         {
  611.             FREE(s_line);
  612.             goto loop;
  613.         }
  614.         if (c == '\n')
  615.             unterminated_string(s_lineno, s_line, s_cptr);
  616.         if (c == '\\')
  617.         {
  618.             c = *cptr++;
  619.             putc(c, text_file);
  620.             if (dflag) putc(c, union_file);
  621.             if (c == '\n')
  622.             {
  623.             get_line();
  624.             if (line == 0)
  625.                 unterminated_string(s_lineno, s_line, s_cptr);
  626.             }
  627.         }
  628.         }
  629.     }
  630.  
  631.     case '/':
  632.     c = *cptr;
  633.     if (c == '/')
  634.     {
  635.         putc('*', text_file);
  636.         if (dflag) putc('*', union_file);
  637.         while ((c = *++cptr) != '\n')
  638.         {
  639.         if (c == '*' && cptr[1] == '/')
  640.         {
  641.             fprintf(text_file, "* ");
  642.             if (dflag) fprintf(union_file, "* ");
  643.         }
  644.         else
  645.         {
  646.             putc(c, text_file);
  647.             if (dflag) putc(c, union_file);
  648.         }
  649.         }
  650.         fprintf(text_file, "*/\n");
  651.         if (dflag) fprintf(union_file, "*/\n");
  652.         goto next_line;
  653.     }
  654.     if (c == '*')
  655.     {
  656.         int c_lineno = lineno;
  657.         char *c_line = dup_line();
  658.         char *c_cptr = c_line + (cptr - line - 1);
  659.  
  660.         putc('*', text_file);
  661.         if (dflag) putc('*', union_file);
  662.         ++cptr;
  663.         for (;;)
  664.         {
  665.         c = *cptr++;
  666.         putc(c, text_file);
  667.         if (dflag) putc(c, union_file);
  668.         if (c == '*' && *cptr == '/')
  669.         {
  670.             putc('/', text_file);
  671.             if (dflag) putc('/', union_file);
  672.             ++cptr;
  673.             FREE(c_line);
  674.             goto loop;
  675.         }
  676.         if (c == '\n')
  677.         {
  678.             get_line();
  679.             if (line == 0)
  680.             unterminated_comment(c_lineno, c_line, c_cptr);
  681.         }
  682.         }
  683.     }
  684.     goto loop;
  685.  
  686.     default:
  687.     goto loop;
  688.     }
  689. }
  690.  
  691.  
  692. #if __STDC__
  693. static int hexval(int c)
  694. #else
  695. static int hexval(c)
  696. int c;
  697. #endif
  698. {
  699.     if (c >= '0' && c <= '9')
  700.     return (c - '0');
  701.     if (c >= 'A' && c <= 'F')
  702.     return (c - 'A' + 10);
  703.     if (c >= 'a' && c <= 'f')
  704.     return (c - 'a' + 10);
  705.     return (-1);
  706. }
  707.  
  708.  
  709. #if __STDC__
  710. static bucket *get_literal(void)
  711. #else
  712. static bucket *get_literal()
  713. #endif
  714. {
  715.     register int c, quote;
  716.     register int i;
  717.     register int n;
  718.     register char *s;
  719.     register bucket *bp;
  720.     int s_lineno = lineno;
  721.     char *s_line = dup_line();
  722.     char *s_cptr = s_line + (cptr - line);
  723.  
  724.     quote = *cptr++;
  725.     cinc = 0;
  726.     for (;;)
  727.     {
  728.     c = *cptr++;
  729.     if (c == quote) break;
  730.     if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
  731.     if (c == '\\')
  732.     {
  733.         char *c_cptr = cptr - 1;
  734.  
  735.         c = *cptr++;
  736.         switch (c)
  737.         {
  738.         case '\n':
  739.         get_line();
  740.         if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
  741.         continue;
  742.  
  743.         case '0': case '1': case '2': case '3':
  744.         case '4': case '5': case '6': case '7':
  745.         n = c - '0';
  746.         c = *cptr;
  747.         if (IS_OCTAL(c))
  748.         {
  749.             n = (n << 3) + (c - '0');
  750.             c = *++cptr;
  751.             if (IS_OCTAL(c))
  752.             {
  753.             n = (n << 3) + (c - '0');
  754.             ++cptr;
  755.             }
  756.         }
  757.         if (n > MAXCHAR) illegal_character(c_cptr);
  758.         c = n;
  759.         break;
  760.  
  761.         case 'x':
  762.         c = *cptr++;
  763.         n = hexval(c);
  764.         if (n < 0 || n >= 16)
  765.             illegal_character(c_cptr);
  766.         for (;;)
  767.         {
  768.             c = *cptr;
  769.             i = hexval(c);
  770.             if (i < 0 || i >= 16) break;
  771.             ++cptr;
  772.             n = (n << 4) + i;
  773.             if (n > MAXCHAR) illegal_character(c_cptr);
  774.         }
  775.         c = n;
  776.         break;
  777.  
  778.         case 'a': c = 7; break;
  779.         case 'b': c = '\b'; break;
  780.         case 'f': c = '\f'; break;
  781.         case 'n': c = '\n'; break;
  782.         case 'r': c = '\r'; break;
  783.         case 't': c = '\t'; break;
  784.         case 'v': c = '\v'; break;
  785.         }
  786.     }
  787.     cachec(c);
  788.     }
  789.     FREE(s_line);
  790.  
  791.     n = cinc;
  792.     s = MALLOC(n);
  793.     
  794.     for (i = 0; i < n; ++i)
  795.     s[i] = cache[i];
  796.  
  797.     cinc = 0;
  798.     if (n == 1)
  799.     cachec('\'');
  800.     else
  801.     cachec('"');
  802.  
  803.     for (i = 0; i < n; ++i)
  804.     {
  805.     c = ((unsigned char *)s)[i];
  806.     if (c == '\\' || c == cache[0])
  807.     {
  808.         cachec('\\');
  809.         cachec(c);
  810.     }
  811.     else if (isprint(c))
  812.         cachec(c);
  813.     else
  814.     {
  815.         cachec('\\');
  816.         switch (c)
  817.         {
  818.         case 7: cachec('a'); break;
  819.         case '\b': cachec('b'); break;
  820.         case '\f': cachec('f'); break;
  821.         case '\n': cachec('n'); break;
  822.         case '\r': cachec('r'); break;
  823.         case '\t': cachec('t'); break;
  824.         case '\v': cachec('v'); break;
  825.         default:
  826.         cachec(((c >> 6) & 7) + '0');
  827.         cachec(((c >> 3) & 7) + '0');
  828.         cachec((c & 7) + '0');
  829.         break;
  830.         }
  831.     }
  832.     }
  833.  
  834.     if (n == 1)
  835.     cachec('\'');
  836.     else
  837.     cachec('"');
  838.  
  839.     cachec(NUL);
  840.     bp = lookup(cache);
  841.     bp->class = TERM;
  842.     if (n == 1 && bp->value == UNDEFINED)
  843.     bp->value = *(unsigned char *)s;
  844.     FREE(s);
  845.  
  846.     return (bp);
  847. }
  848.  
  849.  
  850. #if __STDC__
  851. static int is_reserved(char *name)
  852. #else
  853. static int is_reserved(name)
  854. char *name;
  855. #endif
  856. {
  857.     char *s;
  858.  
  859.     if (strcmp(name, ".") == 0 ||
  860.         strcmp(name, "$accept") == 0 ||
  861.         strcmp(name, "$end") == 0)
  862.     return (1);
  863.  
  864.     if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
  865.     {
  866.     s = name + 3;
  867.     while (isdigit(*s)) ++s;
  868.     if (*s == NUL) return (1);
  869.     }
  870.  
  871.     return (0);
  872. }
  873.  
  874.  
  875. #if __STDC__
  876. static bucket *get_name(void)
  877. #else
  878. static bucket *get_name()
  879. #endif
  880. {
  881.     register int c;
  882.  
  883.     cinc = 0;
  884.     for (c = *cptr; IS_IDENT(c); c = *++cptr)
  885.     cachec(c);
  886.     cachec(NUL);
  887.  
  888.     if (is_reserved(cache)) used_reserved(cache);
  889.  
  890.     return (lookup(cache));
  891. }
  892.  
  893.  
  894. #if __STDC__
  895. static int get_number(void)
  896. #else
  897. static int get_number()
  898. #endif
  899. {
  900.     register int c;
  901.     register int n;
  902.  
  903.     n = 0;
  904.     for (c = *cptr; isdigit(c); c = *++cptr)
  905.     n = 10*n + (c - '0');
  906.  
  907.     return (n);
  908. }
  909.  
  910.  
  911. #if __STDC__
  912. static char *get_tag(void)
  913. #else
  914. static char *get_tag()
  915. #endif
  916. {
  917.     register int c;
  918.     register int i;
  919.     register char *s;
  920.     int t_lineno = lineno;
  921.     char *t_line = dup_line();
  922.     char *t_cptr = t_line + (cptr - line);
  923.  
  924.     ++cptr;
  925.     c = nextc();
  926.     if (c == EOF) unexpected_EOF();
  927.     if (!isalpha(c) && c != '_' && c != '$')
  928.     illegal_tag(t_lineno, t_line, t_cptr);
  929.     else if (! dollar_ok() && c == '$')
  930.     illegal_tag(t_lineno, t_line, t_cptr);
  931.  
  932.     cinc = 0;
  933.     do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
  934.     cachec(NUL);
  935.  
  936.     c = nextc();
  937.     if (c == EOF) unexpected_EOF();
  938.     if (c != '>')
  939.     illegal_tag(t_lineno, t_line, t_cptr);
  940.     ++cptr;
  941.  
  942.     for (i = 0; i < ntags; ++i)
  943.     {
  944.     if (strcmp(cache, tag_table[i]) == 0)
  945.         return (tag_table[i]);
  946.     }
  947.  
  948.     if (ntags >= tagmax)
  949.     {
  950.     tagmax += 16;
  951.     tag_table = (char **)
  952.             (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
  953.                    : MALLOC(tagmax*sizeof(char *)));
  954.     }
  955.  
  956.     s = MALLOC(cinc);
  957.     strcpy(s, cache);
  958.     tag_table[ntags] = s;
  959.     ++ntags;
  960.     FREE(t_line);
  961.     return (s);
  962. }
  963.  
  964.  
  965. #if __STDC__
  966. static void declare_tokens(int assoc)
  967. #else
  968. static void declare_tokens(assoc)
  969. int assoc;
  970. #endif
  971. {
  972.     register int c;
  973.     register bucket *bp;
  974.     int value;
  975.     char *tag = 0;
  976.  
  977.     if (assoc != TOKEN) ++prec;
  978.  
  979.     c = nextc();
  980.     if (c == EOF) unexpected_EOF();
  981.     if (c == '<')
  982.     {
  983.     tag = get_tag();
  984.     c = nextc();
  985.     if (c == EOF) unexpected_EOF();
  986.     }
  987.  
  988.     for (;;)
  989.     {
  990.     if (isalpha(c) || c == '_' || c == '.' || (dollar_ok() && c == '$'))
  991.         bp = get_name();
  992.     else if (c == '\'' || c == '"')
  993.         bp = get_literal();
  994.     else
  995.         return;
  996.  
  997.     if (bp == goal) tokenized_start(bp->name);
  998.     bp->class = TERM;
  999.  
  1000.     if (tag)
  1001.     {
  1002.         if (bp->tag && tag != bp->tag)
  1003.         retyped_warning(bp->name);
  1004.         bp->tag = tag;
  1005.     }
  1006.  
  1007.     if (assoc != TOKEN)
  1008.     {
  1009.         if (bp->prec && prec != bp->prec)
  1010.         reprec_warning(bp->name);
  1011.         bp->assoc = assoc;
  1012.         bp->prec = prec;
  1013.     }
  1014.  
  1015.     c = nextc();
  1016.     if (c == EOF) unexpected_EOF();
  1017.     value = UNDEFINED;
  1018.     if (isdigit(c))
  1019.     {
  1020.         value = get_number();
  1021.         if (bp->value != UNDEFINED && value != bp->value)
  1022.         revalued_warning(bp->name);
  1023.         bp->value = value;
  1024.         c = nextc();
  1025.         if (c == EOF) unexpected_EOF();
  1026.     }
  1027.     }
  1028. }
  1029.  
  1030.  
  1031. #if __STDC__
  1032. static void declare_types(void)
  1033. #else
  1034. static void declare_types()
  1035. #endif
  1036. {
  1037.     register int c;
  1038.     register bucket *bp;
  1039.     char *tag;
  1040.  
  1041.     c = nextc();
  1042.     if (c == EOF) unexpected_EOF();
  1043.     if (c != '<') syntax_error(lineno, line, cptr);
  1044.     tag = get_tag();
  1045.  
  1046.     for (;;)
  1047.     {
  1048.     c = nextc();
  1049.     if (isalpha(c) || c == '_' || c == '.' || (dollar_ok() && c == '$'))
  1050.         bp = get_name();
  1051.     else if (c == '\'' || c == '"')
  1052.         bp = get_literal();
  1053.     else
  1054.         return;
  1055.  
  1056.     if (bp->tag && tag != bp->tag)
  1057.         retyped_warning(bp->name);
  1058.     bp->tag = tag;
  1059.     }
  1060. }
  1061.  
  1062.  
  1063. #if __STDC__
  1064. static void declare_start(void)
  1065. #else
  1066. static void declare_start()
  1067. #endif
  1068. {
  1069.     register int c;
  1070.     register bucket *bp;
  1071.  
  1072.     c = nextc();
  1073.     if (c == EOF) unexpected_EOF();
  1074.     if (!isalpha(c) && c != '_' && c != '.' && c != '$')
  1075.     syntax_error(lineno, line, cptr);
  1076.     else if (! dollar_ok() && c == '$')
  1077.     syntax_error(lineno, line, cptr);
  1078.     bp = get_name();
  1079.     if (bp->class == TERM)
  1080.     terminal_start(bp->name);
  1081.     if (goal && goal != bp)
  1082.     restarted_warning();
  1083.     goal = bp;
  1084. }
  1085.  
  1086.  
  1087. #if __STDC__
  1088. static void read_declarations(void)
  1089. #else
  1090. static void read_declarations()
  1091. #endif
  1092. {
  1093.     register int c, k;
  1094.  
  1095.     cache_size = 256;
  1096.     cache = MALLOC(cache_size);
  1097.  
  1098.     for (;;)
  1099.     {
  1100.     c = nextc();
  1101.     if (c == EOF) unexpected_EOF();
  1102.     if (c != '%') syntax_error(lineno, line, cptr);
  1103.     switch (k = keyword())
  1104.     {
  1105.     case MARK:
  1106.         return;
  1107.  
  1108.     case IDENT:
  1109.         copy_ident();
  1110.         break;
  1111.  
  1112.     case TEXT:
  1113.         copy_text();
  1114.         break;
  1115.  
  1116.     case UNION:
  1117.         copy_union();
  1118.         break;
  1119.  
  1120.     case TOKEN:
  1121.     case LEFT:
  1122.     case RIGHT:
  1123.     case NONASSOC:
  1124.         declare_tokens(k);
  1125.         break;
  1126.  
  1127.     case TYPE:
  1128.         declare_types();
  1129.         break;
  1130.  
  1131.     case START:
  1132.         declare_start();
  1133.         break;
  1134.     }
  1135.     }
  1136. }
  1137.  
  1138.  
  1139. #if __STDC__
  1140. static void initialize_grammar(void)
  1141. #else
  1142. static void initialize_grammar()
  1143. #endif
  1144. {
  1145.     nitems = 4;
  1146.     maxitems = 300;
  1147.     pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
  1148.     pitem[0] = 0;
  1149.     pitem[1] = 0;
  1150.     pitem[2] = 0;
  1151.     pitem[3] = 0;
  1152.  
  1153.     nrules = 3;
  1154.     maxrules = 100;
  1155.     plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
  1156.     plhs[0] = 0;
  1157.     plhs[1] = 0;
  1158.     plhs[2] = 0;
  1159.  
  1160.     rprec = (short *) MALLOC(maxrules*sizeof(short));
  1161.     rprec[0] = 0;
  1162.     rprec[1] = 0;
  1163.     rprec[2] = 0;
  1164.  
  1165.     rassoc = (char *) MALLOC(maxrules*sizeof(char));
  1166.     rassoc[0] = TOKEN;
  1167.     rassoc[1] = TOKEN;
  1168.     rassoc[2] = TOKEN;
  1169. }
  1170.  
  1171.  
  1172. #if __STDC__
  1173. static void expand_items(void)
  1174. #else
  1175. static void expand_items()
  1176. #endif
  1177. {
  1178.     maxitems += 300;
  1179.     pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
  1180. }
  1181.  
  1182.  
  1183. #if __STDC__
  1184. static void expand_rules(void)
  1185. #else
  1186. static void expand_rules()
  1187. #endif
  1188. {
  1189.     maxrules += 100;
  1190.     plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
  1191.     rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
  1192.     rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
  1193. }
  1194.  
  1195.  
  1196. #if __STDC__
  1197. static void advance_to_start(void)
  1198. #else
  1199. static void advance_to_start()
  1200. #endif
  1201. {
  1202.     register int c;
  1203.     register bucket *bp;
  1204.     char *s_cptr;
  1205.     int s_lineno;
  1206.  
  1207.     for (;;)
  1208.     {
  1209.     c = nextc();
  1210.     if (c != '%') break;
  1211.     s_cptr = cptr;
  1212.     switch (keyword())
  1213.     {
  1214.     case MARK:
  1215.         no_grammar();
  1216.  
  1217.     case TEXT:
  1218.         copy_text();
  1219.         break;
  1220.  
  1221.     case START:
  1222.         declare_start();
  1223.         break;
  1224.  
  1225.     default:
  1226.         syntax_error(lineno, line, s_cptr);
  1227.     }
  1228.     }
  1229.  
  1230.     c = nextc();
  1231.     if (!isalpha(c) && c != '_' && c != '.')
  1232.     syntax_error(lineno, line, cptr);
  1233.     bp = get_name();
  1234.     if (goal == 0)
  1235.     {
  1236.     if (bp->class == TERM)
  1237.         terminal_start(bp->name);
  1238.     goal = bp;
  1239.     }
  1240.  
  1241.     s_lineno = lineno;
  1242.     c = nextc();
  1243.     if (c == EOF) unexpected_EOF();
  1244.     if (c != ':') syntax_error(lineno, line, cptr);
  1245.     start_rule(bp, s_lineno);
  1246.     ++cptr;
  1247. }
  1248.  
  1249.  
  1250. #if __STDC__
  1251. static void start_rule(register bucket *bp, int s_lineno)
  1252. #else
  1253. static void start_rule(bp, s_lineno)
  1254. register bucket *bp;
  1255. int s_lineno;
  1256. #endif
  1257. {
  1258.     if (bp->class == TERM)
  1259.     terminal_lhs(s_lineno);
  1260.     bp->class = NONTERM;
  1261.     if (nrules >= maxrules)
  1262.     expand_rules();
  1263.     plhs[nrules] = bp;
  1264.     rprec[nrules] = UNDEFINED;
  1265.     rassoc[nrules] = TOKEN;
  1266. }
  1267.  
  1268.  
  1269. #if __STDC__
  1270. static void end_rule(void)
  1271. #else
  1272. static void end_rule()
  1273. #endif
  1274. {
  1275.     register int i;
  1276.  
  1277.     if (!last_was_action && plhs[nrules]->tag)
  1278.     {
  1279.     for (i = nitems - 1; pitem[i]; --i) continue;
  1280.     if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
  1281.         default_action_warning();
  1282.     }
  1283.  
  1284.     last_was_action = 0;
  1285.     if (nitems >= maxitems) expand_items();
  1286.     pitem[nitems] = 0;
  1287.     ++nitems;
  1288.     ++nrules;
  1289. }
  1290.  
  1291.  
  1292. #if __STDC__
  1293. static void insert_empty_rule(void)
  1294. #else
  1295. static void insert_empty_rule()
  1296. #endif
  1297. {
  1298.     register bucket *bp, **bpp;
  1299.  
  1300.     assert(cache != (char *) NULL);
  1301.     sprintf(cache, "$$%d", ++gensym);
  1302.     bp = make_bucket(cache);
  1303.     last_symbol->next = bp;
  1304.     last_symbol = bp;
  1305.     bp->tag = plhs[nrules]->tag;
  1306.     bp->class = NONTERM;
  1307.  
  1308.     if ((nitems += 2) > maxitems)
  1309.     expand_items();
  1310.     bpp = pitem + nitems - 1;
  1311.     *bpp-- = bp;
  1312.     while (bpp[0] = bpp[-1]) --bpp;
  1313.  
  1314.     if (++nrules >= maxrules)
  1315.     expand_rules();
  1316.     plhs[nrules] = plhs[nrules-1];
  1317.     plhs[nrules-1] = bp;
  1318.     rprec[nrules] = rprec[nrules-1];
  1319.     rprec[nrules-1] = 0;
  1320.     rassoc[nrules] = rassoc[nrules-1];
  1321.     rassoc[nrules-1] = TOKEN;
  1322. }
  1323.  
  1324.  
  1325. #if __STDC__
  1326. static void add_symbol(void)
  1327. #else
  1328. static void add_symbol()
  1329. #endif
  1330. {
  1331.     register int c;
  1332.     register bucket *bp;
  1333.     int s_lineno = lineno;
  1334.  
  1335.     c = *cptr;
  1336.     if (c == '\'' || c == '"')
  1337.     bp = get_literal();
  1338.     else
  1339.     bp = get_name();
  1340.  
  1341.     c = nextc();
  1342.     if (c == ':')
  1343.     {
  1344.     end_rule();
  1345.     start_rule(bp, s_lineno);
  1346.     ++cptr;
  1347.     return;
  1348.     }
  1349.  
  1350.     if (last_was_action)
  1351.     insert_empty_rule();
  1352.     last_was_action = 0;
  1353.  
  1354.     if (++nitems > maxitems)
  1355.     expand_items();
  1356.     pitem[nitems-1] = bp;
  1357. }
  1358.  
  1359.  
  1360. #if __STDC__
  1361. static void copy_action(void)
  1362. #else
  1363. static void copy_action()
  1364. #endif
  1365. {
  1366.     register int c;
  1367.     register int i, n;
  1368.     int depth;
  1369.     int quote;
  1370.     char *tag;
  1371.     register FILE *f = action_file;
  1372.     int a_lineno = lineno;
  1373.     char *a_line = dup_line();
  1374.     char *a_cptr = a_line + (cptr - line);
  1375.  
  1376.     if (last_was_action)
  1377.     insert_empty_rule();
  1378.     last_was_action = 1;
  1379.  
  1380.     if (language == PERL)
  1381.     fprintf(f, "if ($%sn == %d) {\n", symbol_prefix, nrules - 2);
  1382.     else
  1383.     fprintf(f, "case %d:\n", nrules - 2);
  1384.     if (!lflag)
  1385.     fprintf(f, line_format, lineno, input_file_name);
  1386.     if (*cptr == '=') ++cptr;
  1387.  
  1388.     n = 0;
  1389.     for (i = nitems - 1; pitem[i]; --i) ++n;
  1390.  
  1391.     depth = 0;
  1392. loop:
  1393.     c = *cptr;
  1394.     if (c == '$')
  1395.     {
  1396.     if (cptr[1] == '<')
  1397.     {
  1398.         int d_lineno = lineno;
  1399.         char *d_line = dup_line();
  1400.         char *d_cptr = d_line + (cptr - line);
  1401.  
  1402.         ++cptr;
  1403.         tag = get_tag();
  1404.         c = *cptr;
  1405.         if (c == '$')
  1406.         {
  1407.         if (language == PERL)
  1408.             fprintf(f, "$%sval", symbol_prefix);
  1409.         else
  1410.             fprintf(f, "%sval.%s", symbol_prefix, tag);
  1411.         ++cptr;
  1412.         FREE(d_line);
  1413.         goto loop;
  1414.         }
  1415.         else if (isdigit(c))
  1416.         {
  1417.         i = get_number();
  1418.         if (i > n) dollar_warning(d_lineno, i);
  1419.         if (language == PERL)
  1420.             fprintf(f, "$%svs[$%svsp-%d]",
  1421.                 symbol_prefix, symbol_prefix, n - i);
  1422.         else
  1423.             fprintf(f, "%svsp[%d].%s", symbol_prefix, i - n, tag);
  1424.         FREE(d_line);
  1425.         goto loop;
  1426.         }
  1427.         else if (c == '-' && isdigit(cptr[1]))
  1428.         {
  1429.         ++cptr;
  1430.         i = -get_number() - n;
  1431.         if (language == PERL)
  1432.             fprintf(f, "$%svsp[$%svsp-%d]",
  1433.                 symbol_prefix, symbol_prefix, -i);
  1434.         else
  1435.             fprintf(f, "%svsp[%d].%s", symbol_prefix, i, tag);
  1436.         FREE(d_line);
  1437.         goto loop;
  1438.         }
  1439.         else
  1440.         dollar_error(d_lineno, d_line, d_cptr);
  1441.     }
  1442.     else if (cptr[1] == '$')
  1443.     {
  1444.         if (ntags)
  1445.         {
  1446.         tag = plhs[nrules]->tag;
  1447.         if (tag == 0) untyped_lhs();
  1448.         if (language == PERL)
  1449.             fprintf(f, "$%sval", symbol_prefix);
  1450.         else
  1451.             fprintf(f, "%sval.%s", symbol_prefix, tag);
  1452.         }
  1453.         else if (language == PERL)
  1454.         fprintf(f, "$%sval", symbol_prefix);
  1455.         else
  1456.         fprintf(f, "%sval", symbol_prefix);
  1457.         cptr += 2;
  1458.         goto loop;
  1459.     }
  1460.     else if (isdigit(cptr[1]))
  1461.     {
  1462.         ++cptr;
  1463.         i = get_number();
  1464.         if (ntags)
  1465.         {
  1466.         if (i <= 0 || i > n)
  1467.             unknown_rhs(i);
  1468.         tag = pitem[nitems + i - n - 1]->tag;
  1469.         if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
  1470.         if (language == PERL)
  1471.             fprintf(f, "$%svs[$%svsp-%d]",
  1472.                 symbol_prefix, symbol_prefix, n - i);
  1473.         else
  1474.             fprintf(f, "%svsp[%d].%s", symbol_prefix, i - n, tag);
  1475.         }
  1476.         else
  1477.         {
  1478.         if (i > n)
  1479.             dollar_warning(lineno, i);
  1480.         if (language == PERL)
  1481.             fprintf(f, "$%svs[$%svsp-%d]",
  1482.                 symbol_prefix, symbol_prefix, n - i);
  1483.         else
  1484.             fprintf(f, "%svsp[%d]", symbol_prefix, i - n);
  1485.         }
  1486.         goto loop;
  1487.     }
  1488.     else if (cptr[1] == '-')
  1489.     {
  1490.         cptr += 2;
  1491.         i = get_number();
  1492.         if (ntags)
  1493.         unknown_rhs(-i);
  1494.         if (language == PERL)
  1495.         fprintf(f, "$%svs[$%svsp-%d]",
  1496.             symbol_prefix, symbol_prefix, i + n);
  1497.         else
  1498.         fprintf(f, "%svsp[%d]", symbol_prefix, -i - n);
  1499.         goto loop;
  1500.     }
  1501.     }
  1502.     if (isalpha(c) || c == '_' || (dollar_ok() && c == '$'))
  1503.     {
  1504.     do
  1505.     {
  1506.         putc(c, f);
  1507.         c = *++cptr;
  1508.     } while (isalnum(c) || c == '_' || (dollar_ok() && c == '$'));
  1509.     goto loop;
  1510.     }
  1511.     ++cptr;
  1512.     switch (c)
  1513.     {
  1514.     case '\n':
  1515.     putc(c, f);
  1516. next_line:
  1517.     get_line();
  1518.     if (line) goto loop;
  1519.     unterminated_action(a_lineno, a_line, a_cptr);
  1520.  
  1521.     case ';':
  1522.     putc(c, f);
  1523.     if (depth > 0) goto loop;
  1524.     if (language == PERL)
  1525.         fprintf(f, "\nlast switch; }\n");
  1526.     else
  1527.         fprintf(f, "\nbreak;\n");
  1528.     FREE(a_line);
  1529.     return;
  1530.  
  1531.     case '{':
  1532.     putc(c, f);
  1533.     ++depth;
  1534.     goto loop;
  1535.  
  1536.     case '}':
  1537.     if (--depth > 0) {
  1538.         putc(c, f);
  1539.         goto loop;
  1540.     }
  1541.  
  1542.     if (language == PERL)
  1543.         fprintf(f, "\nlast switch;\n} }\n");
  1544.     else
  1545.         fprintf(f, "}\nbreak;\n");
  1546.     FREE(a_line);
  1547.     return;
  1548.  
  1549.     case '\'':
  1550.     case '"':
  1551.     {
  1552.         int s_lineno = lineno;
  1553.         char *s_line = dup_line();
  1554.         char *s_cptr = s_line + (cptr - line - 1);
  1555.  
  1556.         putc(c, f);
  1557.         quote = c;
  1558.         for (;;)
  1559.         {
  1560.         c = *cptr++;
  1561.         putc(c, f);
  1562.         if (c == quote)
  1563.         {
  1564.             FREE(s_line);
  1565.             goto loop;
  1566.         }
  1567.         if (c == '\n')
  1568.             unterminated_string(s_lineno, s_line, s_cptr);
  1569.         if (c == '\\')
  1570.         {
  1571.             c = *cptr++;
  1572.             putc(c, f);
  1573.             if (c == '\n')
  1574.             {
  1575.             get_line();
  1576.             if (line == 0)
  1577.                 unterminated_string(s_lineno, s_line, s_cptr);
  1578.             }
  1579.         }
  1580.         }
  1581.     }
  1582.  
  1583.     case '/':
  1584.     c = *cptr;
  1585.     if (c == '/')
  1586.     {
  1587.         if (language == PERL) {
  1588.         ++cptr;
  1589.         goto perl_comment;
  1590.         }
  1591.         fprintf(f, "/*");
  1592.         while ((c = *++cptr) != '\n')
  1593.         {
  1594.         if (c == '*' && cptr[1] == '/')
  1595.             fprintf(f, "* ");
  1596.         else
  1597.             putc(c, f);
  1598.         }
  1599.         fprintf(f, "*/\n");
  1600.         goto next_line;
  1601.     }
  1602.     if (c != '*')
  1603.     {
  1604.         putc('/', f);
  1605.     }
  1606.     else
  1607.     {
  1608.         int c_lineno = lineno;
  1609.         char *c_line = dup_line();
  1610.         char *c_cptr = c_line + (cptr - line - 1);
  1611.  
  1612.         if (language == PERL)
  1613.         fprintf(f, (cptr == line + 1) ? ";#" : "#");
  1614.         else
  1615.         fprintf(f, "/*");
  1616.         ++cptr;
  1617.         for (;;)
  1618.         {
  1619.         c = *cptr++;
  1620.         if (language == PERL && c == '*' && *cptr == '/')
  1621.         {
  1622.             putc('\n', f);
  1623.             ++cptr;
  1624.             FREE(c_line);
  1625.             goto loop;
  1626.         }
  1627.         putc(c, f);
  1628.         if (c == '*' && *cptr == '/')
  1629.         {
  1630.             putc('/', f);
  1631.             ++cptr;
  1632.             FREE(c_line);
  1633.             goto loop;
  1634.         }
  1635.         if (c == '\n')
  1636.         {
  1637.             get_line();
  1638.             if (line == 0)
  1639.             unterminated_comment(c_lineno, c_line, c_cptr);
  1640.             if (language == PERL)
  1641.             fprintf(f, ";# ");
  1642.         }
  1643.         }
  1644.     }
  1645.     goto loop;
  1646.  
  1647.     case '#':
  1648. perl_comment:
  1649.     if (language == PERL)
  1650.     {
  1651.         putc('#', f);
  1652.         do {
  1653.         putc(*cptr, f);
  1654.         } while (*cptr++ != '\n');
  1655.         goto next_line;
  1656.     }
  1657.     else
  1658.     {
  1659.         putc(c, f);
  1660.     }
  1661.     goto loop;
  1662.  
  1663.     default:
  1664.     putc(c, f);
  1665.     goto loop;
  1666.     }
  1667.  
  1668.     /*NOTREACHED*/ /* or at least it better not be reached*/
  1669. }
  1670.  
  1671.  
  1672. #if __STDC__
  1673. static int mark_symbol(void)
  1674. #else
  1675. static int mark_symbol()
  1676. #endif
  1677. {
  1678.     register int c;
  1679.     register bucket *bp;
  1680.  
  1681.     c = cptr[1];
  1682.     if (c == '%' || c == '\\')
  1683.     {
  1684.     cptr += 2;
  1685.     return (1);
  1686.     }
  1687.  
  1688.     if (c == '=')
  1689.     cptr += 2;
  1690.     else if ((c == 'p' || c == 'P') &&
  1691.          ((c = cptr[2]) == 'r' || c == 'R') &&
  1692.          ((c = cptr[3]) == 'e' || c == 'E') &&
  1693.          ((c = cptr[4]) == 'c' || c == 'C') &&
  1694.          ((c = cptr[5], !IS_IDENT(c))))
  1695.     cptr += 5;
  1696.     else
  1697.     syntax_error(lineno, line, cptr);
  1698.  
  1699.     c = nextc();
  1700.     if (isalpha(c) || c == '_' || c == '.' || (dollar_ok() && c == '$'))
  1701.     bp = get_name();
  1702.     else if (c == '\'' || c == '"')
  1703.     bp = get_literal();
  1704.     else
  1705.     {
  1706.     syntax_error(lineno, line, cptr);
  1707.     /*NOTREACHED*/
  1708.     }
  1709.  
  1710.     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
  1711.     prec_redeclared();
  1712.  
  1713.     rprec[nrules] = bp->prec;
  1714.     rassoc[nrules] = bp->assoc;
  1715.     return (0);
  1716. }
  1717.  
  1718.  
  1719. #if __STDC__
  1720. static void read_grammar(void)
  1721. #else
  1722. static void read_grammar()
  1723. #endif
  1724. {
  1725.     register int c;
  1726.  
  1727.     initialize_grammar();
  1728.     advance_to_start();
  1729.  
  1730.     for (;;)
  1731.     {
  1732.     c = nextc();
  1733.     if (c == EOF) break;
  1734.     if (isalpha(c) || c == '_' || c == '.' || (dollar_ok() && c == '$') || c == '\'' ||
  1735.         c == '"')
  1736.         add_symbol();
  1737.     else if (c == '{' || c == '=')
  1738.         copy_action();
  1739.     else if (c == '|')
  1740.     {
  1741.         end_rule();
  1742.         start_rule(plhs[nrules-1], 0);
  1743.         ++cptr;
  1744.     }
  1745.     else if (c == '%')
  1746.     {
  1747.         if (mark_symbol()) break;
  1748.     }
  1749.     else
  1750.         syntax_error(lineno, line, cptr);
  1751.     }
  1752.     end_rule();
  1753. }
  1754.  
  1755.  
  1756. #if __STDC__
  1757. static void free_tags(void)
  1758. #else
  1759. static void free_tags()
  1760. #endif
  1761. {
  1762.     register int i;
  1763.  
  1764.     if (tag_table == 0) return;
  1765.  
  1766.     for (i = 0; i < ntags; ++i)
  1767.     {
  1768.     assert(tag_table[i] != (char *) NULL);
  1769.     FREE(tag_table[i]);
  1770.     }
  1771.     FREE(tag_table);
  1772. }
  1773.  
  1774.  
  1775. #if __STDC__
  1776. static void pack_names(void)
  1777. #else
  1778. static void pack_names()
  1779. #endif
  1780. {
  1781.     register bucket *bp;
  1782.     register char *p, *s, *t;
  1783.  
  1784.     name_pool_size = sizeof("$end") + sizeof("$accept");
  1785.     for (bp = first_symbol; bp; bp = bp->next)
  1786.     name_pool_size += strlen(bp->name) + 1;
  1787.     name_pool = MALLOC(name_pool_size);
  1788.  
  1789.     strcpy(name_pool, "$accept");
  1790.     strcpy(name_pool + sizeof("$accept"), "$end");
  1791.     t = name_pool + sizeof("$end") + sizeof("$accept");
  1792.     for (bp = first_symbol; bp; bp = bp->next)
  1793.     {
  1794.     p = t;
  1795.     s = bp->name;
  1796.     while (*t++ = *s++) continue;
  1797.     FREE(bp->name);
  1798.     bp->name = p;
  1799.     }
  1800. }
  1801.  
  1802.  
  1803. #if __STDC__
  1804. static void check_symbols(void)
  1805. #else
  1806. static void check_symbols()
  1807. #endif
  1808. {
  1809.     register bucket *bp;
  1810.  
  1811.     if (goal->class == UNKNOWN)
  1812.     undefined_goal(goal->name);
  1813.  
  1814.     for (bp = first_symbol; bp; bp = bp->next)
  1815.     {
  1816.     if (bp->class == UNKNOWN)
  1817.     {
  1818.         undefined_symbol_warning(bp->name);
  1819.         bp->class = TERM;
  1820.     }
  1821.     }
  1822. }
  1823.  
  1824.  
  1825. #if __STDC__
  1826. static void pack_symbols(void)
  1827. #else
  1828. static void pack_symbols()
  1829. #endif
  1830. {
  1831.     register bucket *bp;
  1832.     register bucket **v;
  1833.     register int i, j, k, n;
  1834.  
  1835.     nsyms = 2;
  1836.     ntokens = 1;
  1837.     for (bp = first_symbol; bp; bp = bp->next)
  1838.     {
  1839.     ++nsyms;
  1840.     if (bp->class == TERM) ++ntokens;
  1841.     }
  1842.     start_symbol = ntokens;
  1843.     nvars = nsyms - ntokens;
  1844.  
  1845.     symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
  1846.     symbol_value = (short *) MALLOC(nsyms*sizeof(short));
  1847.     symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
  1848.     symbol_assoc = MALLOC(nsyms);
  1849.  
  1850.     v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
  1851.  
  1852.     v[0] = 0;
  1853.     v[start_symbol] = 0;
  1854.  
  1855.     i = 1;
  1856.     j = start_symbol + 1;
  1857.     for (bp = first_symbol; bp; bp = bp->next)
  1858.     {
  1859.     if (bp->class == TERM)
  1860.         v[i++] = bp;
  1861.     else
  1862.         v[j++] = bp;
  1863.     }
  1864.     assert(i == ntokens && j == nsyms);
  1865.  
  1866.     for (i = 1; i < ntokens; ++i)
  1867.     v[i]->index = i;
  1868.  
  1869.     goal->index = start_symbol + 1;
  1870.     k = start_symbol + 2;
  1871.     while (++i < nsyms)
  1872.     if (v[i] != goal)
  1873.     {
  1874.         v[i]->index = k;
  1875.         ++k;
  1876.     }
  1877.  
  1878.     goal->value = 0;
  1879.     k = 1;
  1880.     for (i = start_symbol + 1; i < nsyms; ++i)
  1881.     {
  1882.     if (v[i] != goal)
  1883.     {
  1884.         v[i]->value = k;
  1885.         ++k;
  1886.     }
  1887.     }
  1888.  
  1889.     k = 0;
  1890.     for (i = 1; i < ntokens; ++i)
  1891.     {
  1892.     n = v[i]->value;
  1893.     if (n > 256)
  1894.     {
  1895.         for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
  1896.         symbol_value[j] = symbol_value[j-1];
  1897.         symbol_value[j] = n;
  1898.     }
  1899.     }
  1900.  
  1901.     if (v[1]->value == UNDEFINED)
  1902.     v[1]->value = 256;
  1903.  
  1904.     j = 0;
  1905.     n = 257;
  1906.     for (i = 2; i < ntokens; ++i)
  1907.     {
  1908.     if (v[i]->value == UNDEFINED)
  1909.     {
  1910.         while (j < k && n == symbol_value[j])
  1911.         {
  1912.         while (++j < k && n == symbol_value[j]) continue;
  1913.         ++n;
  1914.         }
  1915.         v[i]->value = n;
  1916.         ++n;
  1917.     }
  1918.     }
  1919.  
  1920.     symbol_name[0] = name_pool + 8;
  1921.     symbol_value[0] = 0;
  1922.     symbol_prec[0] = 0;
  1923.     symbol_assoc[0] = TOKEN;
  1924.     for (i = 1; i < ntokens; ++i)
  1925.     {
  1926.     symbol_name[i] = v[i]->name;
  1927.     symbol_value[i] = v[i]->value;
  1928.     symbol_prec[i] = v[i]->prec;
  1929.     symbol_assoc[i] = v[i]->assoc;
  1930.     }
  1931.     symbol_name[start_symbol] = name_pool;
  1932.     symbol_value[start_symbol] = -1;
  1933.     symbol_prec[start_symbol] = 0;
  1934.     symbol_assoc[start_symbol] = TOKEN;
  1935.     for (++i; i < nsyms; ++i)
  1936.     {
  1937.     k = v[i]->index;
  1938.     symbol_name[k] = v[i]->name;
  1939.     symbol_value[k] = v[i]->value;
  1940.     symbol_prec[k] = v[i]->prec;
  1941.     symbol_assoc[k] = v[i]->assoc;
  1942.     }
  1943.  
  1944.     FREE(v);
  1945. }
  1946.  
  1947.  
  1948. #if __STDC__
  1949. static void pack_grammar(void)
  1950. #else
  1951. static void pack_grammar()
  1952. #endif
  1953. {
  1954.     register int i, j;
  1955.     int assoc, prec;
  1956.  
  1957.     ritem = (short *) MALLOC(nitems*sizeof(short));
  1958.     rlhs = (short *) MALLOC(nrules*sizeof(short));
  1959.     rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
  1960.     rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
  1961.     rassoc = REALLOC(rassoc, nrules);
  1962.  
  1963.     ritem[0] = -1;
  1964.     ritem[1] = goal->index;
  1965.     ritem[2] = 0;
  1966.     ritem[3] = -2;
  1967.     rlhs[0] = 0;
  1968.     rlhs[1] = 0;
  1969.     rlhs[2] = start_symbol;
  1970.     rrhs[0] = 0;
  1971.     rrhs[1] = 0;
  1972.     rrhs[2] = 1;
  1973.  
  1974.     j = 4;
  1975.     for (i = 3; i < nrules; ++i)
  1976.     {
  1977.     rlhs[i] = plhs[i]->index;
  1978.     rrhs[i] = j;
  1979.     assoc = TOKEN;
  1980.     prec = 0;
  1981.     while (pitem[j])
  1982.     {
  1983.         ritem[j] = pitem[j]->index;
  1984.         if (pitem[j]->class == TERM)
  1985.         {
  1986.         prec = pitem[j]->prec;
  1987.         assoc = pitem[j]->assoc;
  1988.         }
  1989.         ++j;
  1990.     }
  1991.     ritem[j] = -i;
  1992.     ++j;
  1993.     if (rprec[i] == UNDEFINED)
  1994.     {
  1995.         rprec[i] = prec;
  1996.         rassoc[i] = assoc;
  1997.     }
  1998.     }
  1999.     rrhs[i] = j;
  2000.  
  2001.     FREE(plhs);
  2002.     FREE(pitem);
  2003. }
  2004.  
  2005.  
  2006. #if __STDC__
  2007. static void print_grammar(void)
  2008. #else
  2009. static void print_grammar()
  2010. #endif
  2011. {
  2012.     register int i, j, k;
  2013.     int spacing;
  2014.     register FILE *f = verbose_file;
  2015.  
  2016.     if (!vflag) return;
  2017.  
  2018.     k = 1;
  2019.     for (i = 2; i < nrules; ++i)
  2020.     {
  2021.     if (rlhs[i] != rlhs[i-1])
  2022.     {
  2023.         if (i != 2) fprintf(f, "\n");
  2024.         fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
  2025.         spacing = strlen(symbol_name[rlhs[i]]) + 1;
  2026.     }
  2027.     else
  2028.     {
  2029.         fprintf(f, "%4d  ", i - 2);
  2030.         j = spacing;
  2031.         while (--j >= 0) putc(' ', f);
  2032.         putc('|', f);
  2033.     }
  2034.  
  2035.     while (ritem[k] >= 0)
  2036.     {
  2037.         fprintf(f, " %s", symbol_name[ritem[k]]);
  2038.         ++k;
  2039.     }
  2040.     ++k;
  2041.     putc('\n', f);
  2042.     }
  2043. }
  2044.  
  2045.  
  2046. #if __STDC__
  2047. void reader(void)
  2048. #else
  2049. void reader()
  2050. #endif
  2051. {
  2052.     write_section(banner);
  2053.     create_symbol_table();
  2054.     read_declarations();
  2055.     read_grammar();
  2056.     free_symbol_table();
  2057.     free_tags();
  2058.     pack_names();
  2059.     check_symbols();
  2060.     pack_symbols();
  2061.     pack_grammar();
  2062.     free_symbols();
  2063.     print_grammar();
  2064. }
  2065.